import std.stdio: writefln;
import derelict.sdl.sdl;
import Point;
import Utils;
import maths.Vec;
import Color;

void putPixel(SDL_Surface *surface, vec3 vec, uint pixel){
	putPixel(surface, cast(int)vec.x, cast(int)vec.y, pixel);
}

void putPixel(SDL_Surface *surface, point p, uint pixel){
	putPixel(surface, p.x, p.y, pixel);
}

uint getPixel(SDL_Surface* surface, vec3 vec){
	return getPixel(surface, cast(int)vec.x, cast(int)vec.y);
}

uint getPixelInterp(SDL_Surface* surface, vec3 vec, int w, int h ){
	if(vec.x<w-1 && vec.y < h-1 && vec.x > 1 && vec.y > 1){
		uint[] col = [	getPixel(surface, cast(int)(vec.x+1), cast(int)vec.y),
							getPixel(surface, cast(int)(vec.x), cast(int)vec.y)/+,
							getPixel(surface, cast(int)vec.x-1, cast(int)vec.y),
							getPixel(surface, cast(int)vec.x , cast(int)vec.y-1)+/];
		float a = abs(cast(int)vec.x - vec.x);
		uint r = 0;
		uint g = 0;
		uint b = 0;
		foreach(c;col){
		b += a*(c % 0x100) ;
		c /= 0x100;
		g += a*(c % 0x100) ;
		c /= 0x100;
		r += a*c;
		a = 1-a;
		}
		//b = cast(uint)(b/2);
		//g = cast(uint)(g/2);
		//r = cast(uint)(r/2);
		return 0x010000 * r + 0x000100 *  g +  b;
	}
	else
		return getPixel(surface, cast(int)vec.x, cast(int)vec.y);
}

void putPixel(SDL_Surface *surface, int x, int y, uint pixel)
{
	if(x>=0 && x <xResolution && y >=0 && y < yResolution){
	    int bpp = surface.format.BytesPerPixel;
    	/* Here p is the address to the pixel we want to set */
	    Uint8 *p = cast(Uint8 *)surface.pixels + y * surface.pitch + x * bpp;

    	switch(bpp) {
    	case 1:
        	*p = pixel;
        	break;
    	case 2:
        	*cast(Uint16 *)p = pixel;
        	break;
    	case 3:
        	if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
            	p[0] = (pixel >> 16) & 0xff;
            	p[1] = (pixel >> 8) & 0xff;
            	p[2] = pixel & 0xff;
        	} else {
            	p[0] = pixel & 0xff;
            	p[1] = (pixel >> 8) & 0xff;
            	p[2] = (pixel >> 16) & 0xff;
        	}
        	break;
    	case 4:
        	*cast(Uint32 *)p = pixel;
        	break;
    	}
	}
}

uint getPixel(SDL_Surface *surface, int x, int y)
{
    int bpp = surface.format.BytesPerPixel;
    /* Here p is the address to the pixel we want to retrieve */
    Uint8 *p = cast(Uint8 *)surface.pixels + y * surface.pitch + x * bpp;

    switch(bpp) {
    case 1:
        return *p;

    case 2:
        return cast(uint)*p;

    case 3:
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
            return p[0] << 16 | p[1] << 8 | p[2];
        else
            return p[0] | p[1] << 8 | p[2] << 16;

    case 4:
        return cast(uint)*p;

    default:
        return 0;       /* shouldn't happen, but avoids warnings */
    }
}

void drawPixel(SDL_Surface *surface, int x, int y, uint color){
	int bpp = surface.format.BytesPerPixel;
    Uint8 *  bufp= cast(Uint8 *)surface.pixels + y*surface.pitch + x*bpp;

    switch (bpp) {
    	case 4:
        	bufp[3] = color >> 24;
        case 3:
        	bufp[2] = color >> 16;
        case 2:
        	bufp[1] = color >> 8;
        case 1:
        	bufp[0] = color;
    }
}
